// this header defines functions that help in the process of
// reading the J3DGRAPH files I've found on Super Mario Galaxy

#ifndef J3DGRAPH_HEADER
#define J3DGRAPH_HEADER

// this header needs
#include <stdio.h>
#include "../../FILE.h"

// constants
char * J3DGRAPH_FSTART[2][2] = {{"J3D1", "1D3J"},
                                {"J3D2", "2D3J"}};

// file extensions that are valid with this header
char * J3DGRAPH_FEXT[] = {"bmd", "bdl", "btp"};

// padding string found on original J3DGraph files (taken from cloudmodding)
char J3DGRAPH_PAD_STR[32] = "This is padding data to alignme";

// j3dgraph file header
typedef struct
{
  byte * START;     // byte[4]
  byte * ID;        // byte[4]
  byte * SIZE;      // uint32
  byte * SEC_CNT;   // uint32
  byte * UNKNOWN_1; // byte[16]
} j3dgraph_h;

// j3dgraph generic section
// used when an incomplete j3dgraph is to be made
typedef struct
{
  byte * START; // char[4]
  byte * SIZE;  // uint32
} j3dgraph_gen_sec;

// j3dgraph_t enum
// enum with supported 
// j3dgraph file types
typedef enum
{
  J3DGRAPH_NO_TYPE,
  J3DGRAPH_BMD,
  J3DGRAPH_BDL,
  J3DGRAPH_BTP,
} j3dgraph_t;

// j3dgraph_err_cd enum
// enum with general error 
// codes for a j3dgraph file
typedef enum
{
  J3DGRAPH_ERR_NO_ERR,      // j3dgraph file has no errors
  J3DGRAPH_ERR_UNKNOWN_1,   // unknown 1 is not the usual one (error code not used yet)
  // ...
  /**************/
  J3DGRAPH_ERR_LN, // errors below this (in numeric value) are non-fatal, above are fatal
  /**************/
  J3DGRAPH_ERR_NULL_PATH,   // the j3dgraph file given had a NULL path
  J3DGRAPH_ERR_FILE_START,  // starting char[4] array is not correct
  J3DGRAPH_ERR_LOAD_MEM,    // load_file_mem() was not able to load the file
  J3DGRAPH_ERR_FILE_SIZE,   // stored file size is not correct 
  J3DGRAPH_ERR_ENDIAN,      // file endian wasn't able to be got
  J3DGRAPH_ERR_SEC_SIZE,    // a section has an incorrect stored size
  J3DGRAPH_ERR_SEC_CNT,     // the section count is not correct
  // ...
} j3dgraph_err_cd;

// j3dgraph general structure 
typedef struct
{
  char * PATH;            // extra information I want to be able to see
  byte * DATA;            // the bytes of the file loaded in memory
  umax FSIZE;             // size of the file
  ENDIAN_T ENDIAN;        // my addition (to ease checks)
  j3dgraph_err_cd ERR_CD; // another addition (to ease checks as well)
  j3dgraph_t TYPE;        // to be able to identify what the structure holds
  j3dgraph_h HEADER;      // 32 bytes always (see j3dgraph_h)
  umax SEC_CNT;           // number of sections on the file
  void ** SEC;            // array of pointers to section structures
} j3dgraph;

// j3dgraph_data_t enum
// enum with j3dgraph file data types
typedef enum
{
  J3DGRAPH_UINT8,     // unsigned integer (8 bits)
  J3DGRAPH_UINT16,    // unsigned integer (16 bits)
  J3DGRAPH_UINT32,    // unsigned integer (32 bits)
  J3DGRAPH_SINT16,    // signed integer (16 bits)
  J3DGRAPH_FLOAT32,   // floating point number (32 bits)
  J3DGRAPH_CHAR_ARR,  // character array (not null terminated)
  J3DGRAPH_BYTE_ARR,  // character array (not null terminated)
  J3DGRAPH_STR,       // string (character array null terminated)
  J3DGRAPH_PAD4,      // padding string for a 4 byte alignment
  J3DGRAPH_PAD32,     // padding string for a 32 byte alignment
} j3dgraph_data_t;

// something that seems to be a constant
#define J3DGRAPH_STR_TB_UNKNOWN_1 0xFFFF
// a string table of 1 string 1 ASCII character long
#define J3DGRAPH_MIN_STR_TB_LENGTH 10

// j3dgraph_st_tb_err_cd enum
// enum with general error 
// codes for a j3dgraph string table
typedef enum
{
  J3DGRAPH_STR_TB_ERR_INV_ARGS,       // arguments passed to the string table checking function are invalid
  J3DGRAPH_STR_TB_ERR_INV_ELEM_CNT,   // element count is not correct (related to the size of the string table)
  J3DGRAPH_STR_TB_ERR_INV_STR_OFFSET, // a string offset points in a "out of bounds" zone 
  J3DGRAPH_STR_TB_ERR_INV_STR,        // a string in the string list is invalid (out of bound/encoding)

  J3DGRAPH_STR_TB_ERR_NO_ERR,         // errors below this (in value) are fatal, above or equal are safe
  
  J3DGRAPH_STR_TB_ERR_UNKNOWN_1,      // unknown 1 on string table is not the usual one
  J3DGRAPH_STR_TB_ERR_INV_STR_WEIGHT, // a string on the string inf list has an incorrect string weight
} j3dgraph_str_tb_err_cd;

// j3dgraph_str_tb struct
// struct to be used with JSYSTEM file's string tables
typedef struct
{
  // useful info
  ENDIAN_T ENDIAN;                // string table endian
  j3dgraph_str_tb_err_cd ERR_CD;  // string table error code
  // hooks to the string table loaded in memory
  byte * STR_CNT;                 // uint16
  byte * UNKNOWN_1;               // uint16 (J3DGRAPH_STR_TB_UNKNOWN_1)
  byte * STR_INF_LIST;            // array of uint16 (string weight) and uint16 (string offset location)
  byte * STR_LIST;                // array of strings CP932 or Shift_JIS encoded
} j3dgraph_str_tb;

// functions to check some specific data from j3dgragh files
bool check_j3dgraph_fstart(char * fpath);
ENDIAN_T get_j3dgraph_fendian(char * fpath);

// get specific data from j3dgraph files
umax get_j3dgraph_str_weight(void * str, umax mx_size);
umax get_j3dgraph_padding_size(umax pad_pos, bool is_32);
// print some specific data from j3dgraph files
j3dgraph_str_tb_err_cd check_j3dgraph_str_tb(void * arr, umax mx_size, ENDIAN_T endian);
umax                   get_j3dgraph_str_tb_size(void * arr, umax mx_size, ENDIAN_T endian);
j3dgraph_str_tb *      get_j3dgraph_str_tb(void * src, umax src_size, ENDIAN_T endian);
void                   close_j3dgraph_str_tb(j3dgraph_str_tb * str_tb);
void                   print_j3dgraph_str_tb(j3dgraph_str_tb * str_tb);

// build, close and print an incomplete j3dgraph structure (a complete build
// will have to be made by more file type specific functions)
j3dgraph_err_cd check_j3dgraph_inc(char * fpath);
j3dgraph * open_j3dgraph_inc(char * fpath);
void close_j3dgraph_inc(j3dgraph * file);
void print_j3dgraph_start(j3dgraph * file);
void print_j3dgraph_inc(j3dgraph * file);

#include "J3DGRAPH.c"

#endif // J3DGRAPH_HEADER
